﻿Imports NewHeaderSystems.Archive.Engine
Imports EnterpriseDT.Net.Ftp

Public Class FtpDownloader
    Dim WithEvents ftp As New FTPConnection

    Private _worker As System.ComponentModel.BackgroundWorker
    Private _fileSize As Long
    Private _lastReportedPercent As Long
    Private _currentMessage As String

    Public Sub New(ByVal woker As System.ComponentModel.BackgroundWorker)
        _worker = woker
    End Sub

    Private Sub Ftp_Connecting(ByVal sender As System.Object, ByVal e As EnterpriseDT.Net.Ftp.FTPConnectionEventArgs) Handles ftp.Connecting
        _worker.ReportProgress(0, "Connecting...")
    End Sub

    Private Sub Ftp_Connected(ByVal sender As System.Object, ByVal e As EnterpriseDT.Net.Ftp.FTPConnectionEventArgs) Handles ftp.Connected
        _worker.ReportProgress(0, "Connected")
    End Sub

    Private Sub Ftp_BytesTransferred(ByVal sender As System.Object, ByVal e As EnterpriseDT.Net.Ftp.BytesTransferredEventArgs) Handles ftp.BytesTransferred
        If _worker.CancellationPending Then
            ftp.CancelTransfer()
        End If
        Try
            If (_fileSize > 0) Then
                Dim progress As Integer = CInt((e.ByteCount / _fileSize) * 100)
                'Sometimes the bytecount is reported incorrectly. Don't report it when this happens.
                If _fileSize > e.ByteCount And progress > _lastReportedPercent + 10 Then 'Report only 10% increments. Reporting every byte causes stack overflow.
                    _worker.ReportProgress(progress, _currentMessage)
                    _lastReportedPercent = progress
                End If
            End If
        Catch ex As Exception
        End Try
    End Sub

    Public Function DownloadMatchingFiles() As Integer
        Dim settings As SystemSettings = SystemSettings.Instance
        Dim filesToDownload As New List(Of FTPFile)
        With ftp
            Try
                .ServerAddress = settings.FtpServer
                .ServerPort = 21
                .UserName = settings.FtpUsername
                .Password = settings.FtpPassword
                .ConnectMode = FTPConnectMode.PASV
                .TransferType = FTPTransferType.BINARY

                ' Connect, get files and close
                .Connect()

                _worker.ReportProgress(0, "Searching for files to download...")
                If Not String.IsNullOrEmpty(settings.FtpChangeDirectory) Then
                    .ChangeWorkingDirectory(settings.FtpChangeDirectory)
                End If

                If _worker.CancellationPending Then GoTo CancelDownload

                Dim ftpFiles() = .GetFileInfos()
                For Each file As FTPFile In ftpFiles
                    If _worker.CancellationPending Then GoTo CancelDownload
                    If Processor.IsMatchingFile(file.Name) Then
                        filesToDownload.Add(file)
                    End If
                Next

                If filesToDownload.Count > 0 Then
                    Dim index As Integer = 0
                    For Each file As FTPFile In filesToDownload
                        If _worker.CancellationPending Then GoTo CancelDownload
                        index += 1
                        _fileSize = file.Size 'Remember the size of the current file being downloaded, we need this to report on the progress.
                        _lastReportedPercent = 0
                        _currentMessage = String.Format("Downloading {0} (file {1} of {2})", file.Name, index, filesToDownload.Count)
                        _worker.ReportProgress(0, _currentMessage)
                        .DownloadFile(settings.DataFilePath, file.Name)
                    Next
                Else
                    _worker.ReportProgress(0, "There are no files available to download.")
                End If
CancelDownload:
                .Close()                
                Return -1 'Cancellation

            Catch ex As FTPTransferCancelledException
                .Close() 'Cancellation when bytes were being transferred.
                Return -1
            Catch ex As Exception
                If .IsConnected Then
                    .Close()
                End If
                'TODO: Write to log
            End Try


        End With
    End Function
End Class

